package cn.ava.ymcc.service.impl;



import cn.ava.exception.GlobleException;
import cn.ava.ymcc.config.GraphCodeProperties;
import cn.ava.ymcc.config.SmsCodeProperties;
import cn.ava.ymcc.constants.*;
import cn.ava.ymcc.domain.MessageSms;
import cn.ava.ymcc.dto.RedisSMSCodeValueDTO;
import cn.ava.ymcc.dto.SmsRegisterDto;
import cn.ava.ymcc.service.IMessageSmsService;
import cn.ava.ymcc.service.IVerifyCodeService;
import cn.ava.ymcc.utils.AssertUtil;
import cn.ava.ymcc.utils.StrUtils;
import cn.ava.ymcc.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private GraphCodeProperties graphCodeProperties;

    @Autowired
    private SmsCodeProperties smsCodeProperties;

    @Autowired
    private IMessageSmsService messageSmsService;

    @Override
    public String getGraph(String imageCodeKey) {
        // 调用字符串工具类获取随机四位数字符串
        String code = StrUtils.getComplexRandomString(graphCodeProperties.getLength());
        // 将随机数设置进redis中
        redisTemplate.opsForValue().set(imageCodeKey, code, graphCodeProperties.getExpire(), TimeUnit.MINUTES);
        // 将code值转换为图形并编译成Base64
        return VerifyCodeUtils.verifyCode(graphCodeProperties.getWidth(),graphCodeProperties.getHeight(),code);
    }



    @Override
    public void smsCode(SmsRegisterDto smsRegisterDto) {
        // 图形验证码
        String imageCode = smsRegisterDto.getImageCode();
        // 图形验证码key
        String imageCodeKey = smsRegisterDto.getImageCodeKey();
        // 用户手机号
        String mobile = smsRegisterDto.getMobile();
        // 从redis中获取图形验证码
        String redisImageCode = (String)redisTemplate.opsForValue().get(imageCodeKey);
        // 判断是否存在
        AssertUtil.isNotEmpty(redisImageCode,"验证码不存在,请重新获取!");
        // 判断是否一致
        AssertUtil.isEqualsIgnoreCase(redisImageCode,imageCode,"验证码错误,请重新输入!");
        // 判断是否存在短信验证码
        String redisRegisterKey = CommonConstants.UserConstant.BUSINESS_REGISTER_KEY + mobile;
        RedisSMSCodeValueDTO redisSMSCodeValueDTO = (RedisSMSCodeValueDTO)redisTemplate.opsForValue().get(redisRegisterKey);
        // 不存在
        if (redisSMSCodeValueDTO == null) {
            // 直接生成新的短信验证码对象发送
            redisSMSCodeValueDTO = new RedisSMSCodeValueDTO(
                    StrUtils.getComplexRandomString(smsCodeProperties.getLength()),new Date());

        }else if ((System.currentTimeMillis()-redisSMSCodeValueDTO.getCreateDate().getTime()) < smsCodeProperties.getInterval()) {
            // 存在 判断发送时间是否大于一分钟
            throw new GlobleException("发送时间间隔太短,请稍后再试!","403");
        }
        // 存入redis
        redisTemplate.opsForValue().set(redisRegisterKey,redisSMSCodeValueDTO,smsCodeProperties.getExpire(),TimeUnit.MINUTES);
        // 发送短信
//        SendSmsUtil.SendSms(smsRegisterDto.getMobile(),"尊敬的用户您好,\n您的手机验证码为: " + redisSMSCodeValueDTO.getCode());
        insertSMSSendLog(smsRegisterDto,"手机号:  " + smsRegisterDto.getMobile() + " 验证码: " + redisSMSCodeValueDTO.getCode());
        log.error("短信验证码{}\r",redisSMSCodeValueDTO.getCode());
    }


    private void insertSMSSendLog(SmsRegisterDto dto,String message){
        //创建消息实体类
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("用户注册短信验证码");
        messageSms.setContent(message);
        //获取ip地址 start
        ServletRequestAttributes servletRequestAttributes =  (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
        messageSms.setIp( httpServletRequest.getRemoteAddr());
        //获取ip地址 end
        messageSms.setSendTime(new Date());
        messageSmsService.insert(messageSms);
        log.info(messageSms.getId().toString());
    }


}
